package controllers

import (
	"goravel/app/models"
	"goravel/app/scopes"
	"goravel/app/services"
	"goravel/utils/response"
	"strconv"

	"github.com/goravel/framework/contracts/http"
	"github.com/goravel/framework/facades"
)

type CategoriesController struct {
	service *services.CategoryService
}

func NewCategoriesController() *CategoriesController {
	return &CategoriesController{
		service: services.NewCategoryService(),
	}
}

// GetSubordinateIDs 获取所有下级分类 ID
func (c *CategoriesController) GetSubordinateIDs(ctx http.Context) http.Response {
	var model models.Categorie

	if err := scopes.Query(ctx).FindOrFail(&model, ctx.Request().RouteInt("id")); err != nil {
		return response.Fail(ctx, http.StatusNotFound, facades.Lang(ctx).Get("errors.failed_to_fetch"))
	}

	subordinateIDs, err := c.service.GetSubordinateIDs(ctx, uint(model.ID))
	if err != nil {
		facades.Log().Error("Failed to fetch subordinate IDs: ", err)
		return response.Fail(ctx, http.StatusInternalServerError, facades.Lang(ctx).Get("errors.failed_to_fetch"))
	}

	return response.Success(ctx, http.Json{
		"subordinate_ids": subordinateIDs,
	})
}

// Index 获取所有分类并以树形结构返回
func (c *CategoriesController) Index(ctx http.Context) http.Response {
	tree, err := c.service.GetAllCategories(ctx)
	if err != nil || tree == nil {
		tree = []map[string]any{}
	}
	return response.Success(ctx, http.Json{
		"data": tree,
	})
}

// Show 获取单个分类详情
func (c *CategoriesController) Show(ctx http.Context) http.Response {
	var model models.Categorie

	if err := scopes.Query(ctx).FindOrFail(&model, ctx.Request().RouteInt("id")); err != nil {
		return response.Fail(ctx, http.StatusNotFound, facades.Lang(ctx).Get("errors.failed_to_fetch"))
	}

	return response.Success(ctx, http.Json{
		"data": model,
	})
}

// Store 创建分类
func (c *CategoriesController) Store(ctx http.Context) http.Response {

	validator, err := facades.Validation().Make(ctx.Request().All(),
		map[string]string{
			"name":      "required|string",
			"parent_id": "uint",
			"type":      "uint",
			// "sort":      "regex:^-?\\d+(\\.\\d+)?$",
			"sort": "float",
		})

	// input := ctx.Request().All()
	// rules := map[string]string{
	// 	"name":      "required|string",
	// 	"parent_id": "uint",
	// 	"type":      "uint",
	// 	"sort":      "int",
	// }

	// validator, err := facades.Validation().Make(input, rules, validation.PrepareForValidation(func(ctx http.Context, data validationcontract.Data) error {
	// 	if sortStr, exist := data.Get("sort"); exist {
	// 		if sortStrStr, ok := sortStr.(string); ok {
	// 			sortInt, err := strconv.Atoi(sortStrStr)
	// 			if err != nil {
	// 				return err
	// 			}
	// 			return data.Set("sort", sortInt)
	// 		}
	// 	}
	// 	return nil
	// }))

	if err != nil {
		return response.Fail(ctx, http.StatusBadRequest, "Validation failed: "+err.Error())
	}

	if validator.Fails() {
		return response.Fail(ctx, http.StatusBadRequest, validator.Errors().One())
	}

	parentID, _ := strconv.ParseUint(ctx.Request().Input("parent_id"), 10, 32)
	categoryType, _ := strconv.ParseUint(ctx.Request().Input("type"), 10, 8)
	sort, _ := strconv.ParseInt(ctx.Request().Input("sort"), 10, 64)

	category := models.Categorie{
		Name:     ctx.Request().Input("name"),
		ParentID: uint(parentID),
		Type:     uint8(categoryType),
		Sort:     sort,
	}

	if err := scopes.Create(ctx, &category); err != nil {
		facades.Log().Error("Failed to create category: ", err)
		return response.Fail(ctx, http.StatusInternalServerError, facades.Lang(ctx).Get("errors.failed_to_create"))
	}

	return response.Success(ctx, http.Json{
		"data": category,
	})
}

// Update 更新分类
func (c *CategoriesController) Update(ctx http.Context) http.Response {

	var model models.Categorie
	if err := scopes.Query(ctx).FindOrFail(&model, ctx.Request().RouteInt("id")); err != nil {
		return response.Fail(ctx, http.StatusNotFound, facades.Lang(ctx).Get("errors.failed_to_fetch"))
	}

	validator, err := ctx.Request().Validate(map[string]string{
		"name":     "string",
		"sort":     "float",
		"parentID": "uint",
	})

	if err != nil {
		return response.Fail(ctx, http.StatusBadRequest, "Validation failed: "+err.Error())
	}

	if validator.Fails() {
		return response.Fail(ctx, http.StatusBadRequest, validator.Errors().One())
	}

	if name := ctx.Request().Input("name"); name != "" {
		model.Name = name
	}

	if sort := ctx.Request().Input("sort"); sort != "" {
		sortValue, err := strconv.Atoi(sort)
		if err != nil {
			return response.Fail(ctx, http.StatusBadRequest, facades.Lang(ctx).Get("errors.invalid_value"))
		}
		model.Sort = int64(sortValue)
	}

	if parentID := ctx.Request().Input("parent_id"); parentID != "" {
		parentIDValue, err := strconv.ParseUint(parentID, 10, 32)
		if err != nil {
			return response.Fail(ctx, http.StatusBadRequest, facades.Lang(ctx).Get("errors.invalid_value"))
		}
		model.ParentID = uint(parentIDValue)
	}

	if ctype := ctx.Request().Input("type"); ctype != "" {
		typeValue, err := strconv.ParseUint(ctype, 10, 8)
		if err != nil {
			return response.Fail(ctx, http.StatusBadRequest, facades.Lang(ctx).Get("errors.invalid_value"))
		}
		model.Type = uint8(typeValue)
	}

	if err := scopes.Query(ctx).Save(&model); err != nil {
		return response.Fail(ctx, http.StatusInternalServerError, facades.Lang(ctx).Get("errors.failed_to_update"))
	}

	return response.Success(ctx, http.Json{
		"data": model,
	})
}

// Destroy 删除分类
func (c *CategoriesController) Destroy(ctx http.Context) http.Response {

	var model models.Categorie

	res, err := scopes.Query(ctx).Model(&model).Where("id", ctx.Request().RouteInt("id")).Delete()
	if err != nil {
		return response.Fail(ctx, http.StatusInternalServerError, facades.Lang(ctx).Get("errors.failed_to_delete"))
	}

	if res.RowsAffected == 0 {
		return response.Fail(ctx, http.StatusNotFound, facades.Lang(ctx).Get("errors.no_deleted"))
	}

	return response.Success(ctx, http.Json{
		"id":            model.ID,
		"rows_affected": res.RowsAffected,
	})
}
